import fp from 'lodash/fp';
import qs from 'qs';

/**
 * addQueryToUrl方法的选项
 * @interface IAddQueryToUrlOptions
 */
interface IAddQueryToUrlOptions {
  /** url */
  url?: string;
  /** 查询字符串，也可以是个对象 */
  query?: string | object;
  /** 是否覆盖更新query，
   * 比如addQueryToUrl({url:'xxx?a=1',query:{a:2},mergeQuery:true})将会是xxx?a=2，而不是xxx?a=1&a=2
   * */
  mergeQuery?: boolean;
}

/**
 * 将query添加到url上。
 * 注意:如果query中项的值是一个对象或者数组,
 * 将会JSON.stringify这个值(这与qs),如果要还原这个值,请使用JSON.parse(decodeURIComponent(decodeURIComponent(value)))。
 * 如果想将query还原成对象,可以使用formatQuery方法。
 *
 * @export
 * @since 1.0.2
 * @param {IAddQueryToUrlOptions} [options]
 * @param {string} [options.url] url
 * @param {string | object} [options.query] 查询字符串，也可以是个对象
 * @param {boolean} [options.mergeQuery] 是否覆盖更新query，
 * @return {string} 拼接好的字符串
 */
export default function addQueryToUrl({ url = '', query = '', mergeQuery = true }:IAddQueryToUrlOptions = { }):string {
  // 参数检查，如果query不存在
  if ((!fp.isString(query) && !fp.isObject(query)) || fp.isEmpty(query)) {
    return url;
  }
  // 处理query
  let queryStr:string = '';
  let newUrl:string = '';
  // 如果query是对象且不为空
  if (fp.isObject(query) && fp.size(query)) {
    try {
      queryStr = qs.stringify(fp.mapValues((value) => {
        // 如果值是对象或者数组（类对象），那么用JSON.stringify转换成字符串
        // 则可以最大程度保证在各个环境中能够正确的还原query
        if (fp.isObjectLike(value)) {
          return JSON.stringify(value);
        }
        return value;
      }, query));
    // eslint-disable-next-line no-empty
    } catch (error) {
    }
    // 否则，如果query是字符串，那么直接使用
  } else if (fp.isString(query)) {
    queryStr = fp.trimChars('?', query);
  }
  // 拼凑url
  if (url.indexOf('?') !== -1) {
    newUrl = `${fp.trimCharsEnd('&', url)}&${fp.trimCharsStart('&', queryStr)}`;
  } else {
    newUrl = `${url}?${queryStr}`;
  }
  // 覆盖更新query
  if (mergeQuery) {
    const newQueryStr = fp.flowRight(
      fp.join('&'),
      fp.map(fp.join('=')),
      fp.toPairs,
      fp.fromPairs,
      fp.map(fp.split('=')),
      fp.split('&'),
      fp.get('[1]'),
      fp.split('?'),
    )(newUrl);
    newUrl = fp.flowRight(
      fp.get('[0]'),
      fp.split('?'),
    )(url);
    newUrl = newQueryStr ? `${newUrl}?${newQueryStr}` : newUrl;
  }
  return newUrl;
}
